package com.authine.cloudpivot.ext.applicationservice;

import cn.hutool.core.date.DateUtil;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.OrganizationNameConstant;
import com.authine.cloudpivot.ext.converter.CustomerOrderConverter;
import com.authine.cloudpivot.ext.dto.CustomerGoodsDTO;
import com.authine.cloudpivot.ext.dto.MuYuanOrderGoodsDTO;
import com.authine.cloudpivot.ext.dto.OrderCustomerQuantityDTO;
import com.authine.cloudpivot.ext.dto.VendorOrderDTO;
import com.authine.cloudpivot.ext.enums.InvoiceStatusEnum;
import com.authine.cloudpivot.ext.enums.OrderGoodsRefundStatusEnum;
import com.authine.cloudpivot.ext.enums.OrderTimeRangeEnum;
import com.authine.cloudpivot.ext.enums.order.OrderGoodsReturnsStatusEnum;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.common.json.JsonUtils;
import com.authine.hermes.app.launcher.service.ApplicationService;
import com.authine.mvp.app.launcher.common.TableHelper;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.ObjectUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

/**
 * @author wangning
 */
@Path("MuYuanVendorService")
@Slf4j
public class MuYuanVendorService extends ApplicationService {


    private final TableHelper tableHelper = ApplicationContextUtils.getBean(TableHelper.class);


    private NamedParameterJdbcTemplate jdbcTemplate = ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);


    public final static BiFunction<OrderCustomerQuantityDTO, Double, Double> quantityFun = (dto, cumulative) -> MYBigDecimalUtils.add(Optional.ofNullable(dto.getQuantity()).orElse(0.0), cumulative);

    /**
     * 因为退款可能为空,所以为空的时候 设置为0
     */
    public final static BiFunction<OrderCustomerQuantityDTO, Double, Double> returnQuantityFun = (dto, cumulative) -> MYBigDecimalUtils.add(Optional.ofNullable(dto.getReturnReceivedQuantity()).orElse(0.0), cumulative);


    public final static BiFunction<Map, Double, Double> mapQuantityFun = (map, cumulative) -> MYBigDecimalUtils.add(Double.valueOf(map.get("quantity").toString()), cumulative);


    /**
     * 牧原订单列表
     * @param vendorOrderDTO
     * @return
     */
    @Path("VendorOrder")
    @Operation(summary = "获取牧原订单信息", tags = CUSTOM_SERVICE,description = "")
    @POST
    public  SingleResponse  VendorOrder(@Parameter VendorOrderDTO vendorOrderDTO){

        log.info("------------------------运营中心-平台客户管理-牧原专场订单 vendorOrder Param：{}------------------------", JSONObject.toJSONString(vendorOrderDTO));



        // TODO: 2021/10/14  增加对应的权限,只搜索牧原订单

        Integer pageIndex = Optional.ofNullable(vendorOrderDTO.getPageIndex()).orElse(0);

        Integer pageSize = Optional.ofNullable(vendorOrderDTO.getPageSize()).orElse(10);



        String orderCustomerTableName = getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER);



        StringBuilder listSql = new StringBuilder();

        StringBuilder countSql = new StringBuilder();

        StringBuilder whereBuilder = new StringBuilder();


        String queryFiled= " a.id," +
                " a.createdTime, " +
                " a.erp_po, " +
                " a.order_customer_status, " +
                " a.place_order_fullname, "+
                " a.address, " +
                " a.invoice_numbers ";


        String countFiled= " COUNT(a.id) ";

        String sqlTable="SELECT %s FROM " +
                orderCustomerTableName+ " a " +

                " where 1=1  and a.deleted=0 ";


        countSql.append(String.format(sqlTable,countFiled ));


        listSql.append(String.format(sqlTable,queryFiled ));

        Map<String, Object> queryParams = new HashMap<>();

        //拼接查询条件
        CustomerOrderConverter.orderSplicer(vendorOrderDTO, whereBuilder, queryParams);


        listSql.append(whereBuilder);
        countSql.append(whereBuilder);

        listSql.append(" limit " + (pageIndex) * pageSize + ", " + pageSize);



        log.info("牧原专区订单查询sql为{}",listSql.toString());
        //进行分页

        log.info("------------------------牧原专场-订单列表 returnOrderList listSql：{}------------------------parameter：{}", listSql, JsonUtils.toJson(queryParams)+"----------");
        log.info("------------------------牧原专场-订单列表 returnOrderList whereBuilder：{}------------------------parameter：{}", whereBuilder, listSql, JsonUtils.toJson(queryParams)+"--------");


        List<Map<String, Object>> maps = jdbcTemplate.queryForList(listSql.toString(), queryParams);

        //如果搜索为空,则直接返回
        if (CollectionUtils.isEmpty(maps)){
            BOList boList = new BOList();
            SingleResponse singleResponse = new SingleResponse();
            singleResponse.setData(boList);
            return singleResponse;
        }

        //查询总条数

        int  count=0;
        try {
            count= jdbcTemplate.queryForObject(countSql.toString(), queryParams,Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }


        //计算未交付数量
        setupUndeliveredQuantity(maps);

        //构建结果集
       // BoResultFormat.resultFormat(maps, ModelConst.T_ORDER_CUSTOMER);
        BOList bOList = new BOList();
        bOList.setData(maps);
        bOList.setTotal(count);
        bOList.setSchemaCode(ModelConst.T_ORDER_VENDOR_GOODS);
        return SingleResponse.of(bOList);

    }



    /**
     * 牧原订单商品列表
     * @param customerGoodsDTO
     * @return
     */
    @Path("CustomerGoods")
    @Operation(summary = "牧原订单商品信息", tags = CUSTOM_SERVICE,description = "")
    @POST
    public  SingleResponse  CustomerGoods(@Parameter CustomerGoodsDTO customerGoodsDTO){

        log.info("------------------------运营中心-平台客户管理-牧原专场订单商品 CustomerOrder Param：{}------------------------", JSONObject.toJSONString(customerGoodsDTO));


        //查询条件



        // TODO: 2021/10/14  增加对应的权限,只搜索牧原订单

        Integer pageIndex = Optional.ofNullable(customerGoodsDTO.getPageIndex()).orElse(0);

        Integer pageSize = Optional.ofNullable(customerGoodsDTO.getPageSize()).orElse(10);



        String orderCustomerGoodsTableName = getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS);



        String orderCustomerTableName = getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER);


        StringBuilder listSql = new StringBuilder();

        StringBuilder countSql = new StringBuilder();

        StringBuilder whereBuilder = new StringBuilder();


        String organizationName= Optional.ofNullable(customerGoodsDTO.getOrganizationName()).orElse(OrganizationNameConstant.MY_ORGANIZATION_NAME);


        //查询字段
        String queryFiled= "SELECT  a.id, " +
                        " a.place_order_time," +
                        " a.erp_po," +
                        "orderCustomer.address," +
                        "a.receiver," +
                        "a.place_order_fullname, "+
                        "sku," +
                        "order_customer_goods_status," +
                        "a.name," +
                        "brand," +
                        "model," +
                        "description," +
                        "clarify_tips," +
                        "quantity," +
                        "unit," +
                        "vendor_organization_name," +
                        "a.invoice_numbers," +
                        "images," +
                        "a.quantity_received,"+
                        "a.quantity_shipped,"+
                        "returned_num," +
                        "orderCustomer.order_customer_status," +
                        "orderCustomer.after_sale," +
                        "orderCustomer.enabled," +
                        "return_received_num," +
                        "JSON_VALID( images ) AS ifStatus, " +
                        " a.returned_num as returnedQuantity ,  " +
                        " a.return_received_num  as returnReceivedQuantity"+
                        " FROM "+
                         orderCustomerGoodsTableName+ " a " +
                        "left join " + orderCustomerTableName+ " as orderCustomer " +
                        " ON a.order_customer_id=orderCustomer.id "+
                        " where  a.deleted=0 and orderCustomer.deleted =0 "+
                        " and  a.customer_organization_name = '"+organizationName+"' ";

        String countFiled= "select  COUNT(a.id)  from (%s) a where 1=1";

        String sqlTable="select * from  (%s) a where 1=1";


        countSql.append(String.format(countFiled,queryFiled ));


        listSql.append(String.format(sqlTable,queryFiled ));

        Map<String, Object> queryParams = new HashMap<>();

        //客户订单商品拼接查询条件
        CustomerOrderConverter.goodsSplicer(customerGoodsDTO,whereBuilder,queryParams);




        listSql.append(whereBuilder);
        countSql.append(whereBuilder);

        listSql.append(" limit " + (pageIndex) * pageSize + ", " + pageSize);



        log.info("牧原专区订单查询sql为{}",listSql.toString());
        //进行分页

        log.info("------------------------牧原专场-商品列表 returnOrderList listSql：{}------------------------parameter：{}", listSql, JsonUtils.toJson(queryParams)+"----------");
        log.info("------------------------牧原专场-商品列表 returnOrderList whereBuilder：{}------------------------parameter：{}", whereBuilder, listSql, JsonUtils.toJson(queryParams)+"--------");


        List<Map<String, Object>> maps = jdbcTemplate.queryForList(listSql.toString(), queryParams);

        //如果搜索为空,则直接返回
        if (CollectionUtils.isEmpty(maps)){
            BOList boList = new BOList();
            SingleResponse singleResponse = new SingleResponse();
            singleResponse.setData(boList);
            return singleResponse;
        }

        //查询总条数

        int  count=0;
        try {
            count= jdbcTemplate.queryForObject(countSql.toString(), queryParams,Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }



        //计算未交付数量

       setupGoodsUndeliveredQuantity(maps);




        //构建结果集

        BOList bOList = new BOList();
        bOList.setData(maps);
        bOList.setTotal(count);
        bOList.setSchemaCode(ModelConst.T_ORDER_VENDOR_GOODS);
        return SingleResponse.of(bOList);

    }




    /**
     * 计算订单未交付商品数量
     * @param maps
     *
     */
    private void  setupUndeliveredQuantity(List<Map<String, Object>> maps){



        String  orderCustomerGoodsTableName= getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS);


        //退货商品表
        String orderGoodsReturnsTableName = getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RETURNS);

        //商品收货记录表
        String orderGoodsAcceptTableName = getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_ACCEPT);



        //获取订单id
        List<String> orderCustomerId = maps.stream().map(x -> String.valueOf(x.get("id"))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(orderCustomerId)) {
            return;
        }

        String whereSql = orderCustomerId.stream().map(x -> "\'" + x + "\'").collect(Collectors.joining(",", "(", ")"));

        String goodsSql="select order_customer_id as id,quantity,return_received_num as returnReceivedQuantity  from " +
                orderCustomerGoodsTableName+
                " where  order_customer_id IN " + whereSql +"and deleted=0";


        //查询 t_order_customer_goods 表数据   数量 quantity相加
        List<OrderCustomerQuantityDTO> goodsQuantityList = getQuantityList(orderCustomerGoodsTableName, goodsSql,OrderCustomerQuantityDTO.class);


        //查询t_order_goods_returns数据  退货商品表

        String returnsSql="select order_customer_id as id,quantity, 0.0 as \"returnReceivedQuantity\" ,order_goods_returns_status as status from " +
                orderGoodsReturnsTableName+
                " where  order_customer_id IN " + whereSql +"and deleted=0";

        List<OrderCustomerQuantityDTO> refundQuantityList=getQuantityList(orderCustomerGoodsTableName, returnsSql,OrderCustomerQuantityDTO.class);



        //获取订单商品收货信息
        String acceptSql="select a.order_customer_id as id, a.quantity,  0.0 AS \"returnReceivedQuantity\"  from " +
                 orderCustomerGoodsTableName+ " a "+
                "left join " +
                orderGoodsAcceptTableName + " b "+
                "on a.id=b.order_customer_goods_id"+
                " where  order_customer_id IN " + whereSql +"and a.deleted=0 and b.deleted=0";

        List<OrderCustomerQuantityDTO> acceptQuantityList=getQuantityList(orderCustomerGoodsTableName, acceptSql,OrderCustomerQuantityDTO.class);

        //计算
        for (Map<String, Object> map : maps) {
            //计算商品总和
            double goodsQuantity = sum(goodsQuantityList.stream().filter(t -> t.getId().equals(String.valueOf(map.get("id")))).collect(Collectors.toList()), quantityFun);

            //计算 商品退货
            double refundQuantity = sum(refundQuantityList.stream().filter(t -> t.getId().equals(String.valueOf(map.get("id")))).collect(Collectors.toList()), quantityFun);


            //计算 商品收货表数量
            double receivedQuantity = sum(acceptQuantityList.stream().filter(t -> t.getId().equals(String.valueOf(map.get("id")))).collect(Collectors.toList()), quantityFun);


            //客户订单  退的收货数量   return_received_num
            double goodsReturnReceivedQuantity = sum(goodsQuantityList.stream().filter(t -> t.getId().equals(String.valueOf(map.get("id")))).collect(Collectors.toList()), returnQuantityFun);


            //计算    退货商品 过滤 非待收货 5  以及 非退货中 7 的状态
            List<OrderCustomerQuantityDTO> tempRefundQuantityList = refundQuantityList.stream().filter(t->t.getId().equals(String.valueOf(map.get("id")))).filter(t -> !OrderGoodsReturnsStatusEnum.Done.name().equals(t.getStatus())).collect(Collectors.toList());

            //商品收货表数量 不为空以及 待收货 5  以及 非退货中 7  不为空,计算收货数量-退货数量
            if (receivedQuantity > 0 && !CollectionUtils.isEmpty(tempRefundQuantityList)) {
                //计算退货数量    可以用refundQuantity  代替
                double tempRefundQuantity = sum(refundQuantityList.stream().filter(t -> t.getId().equals(String.valueOf(map.get("id")))).collect(Collectors.toList()), quantityFun);
                //退的收货数量 > 如果商品数量-退货数量
                if (tempRefundQuantity > MYBigDecimalUtils.sub(receivedQuantity, goodsReturnReceivedQuantity)) {
                    //退的收货数量
                    goodsReturnReceivedQuantity = receivedQuantity;
                } else {
                    //退的收货数量  refundQuantity + 退的收货数量
                    goodsReturnReceivedQuantity = MYBigDecimalUtils.add(tempRefundQuantity, goodsReturnReceivedQuantity);
                }
            }

            //总退数量-退已收货数量，为什么这么做：退已收的和已收货数量相重叠
            refundQuantity = MYBigDecimalUtils.sub(refundQuantity, goodsReturnReceivedQuantity);
            //计算商品总和-商品收货表数量-(总退数量-退已收货数量)
            double undeliveredQuantity = MYBigDecimalUtils.sub(MYBigDecimalUtils.sub(goodsQuantity, receivedQuantity), refundQuantity);
            map.put("extends_attr",undeliveredQuantity);

        }

    }

    /**
     * 订单商品
     * @param maps
     */
    private void  setupGoodsUndeliveredQuantity( List<Map<String, Object>> maps){
        //转换


        //物流跟踪表
        String  orderTraceTableName= getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_TRACE);


        //退货商品表
        String orderGoodsReturnsTableName = getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RETURNS);

        //商品收货记录表
        String orderGoodsAcceptTableName = getTableName(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_ACCEPT);





        String whereSql = maps.stream().map(x -> "\'" + x.get("id").toString() + "\'").collect(Collectors.joining(",", "(", ")"));

        String goodsSql="select order_customer_goods_id as id,quantity,0.0 as returnReceivedQuantity,-1 status from " +
                orderTraceTableName+
                " where  order_customer_goods_id  IN " + whereSql +" and deleted = 0";


        //查询 t_order_customer_goods 物流跟踪表   数量 quantity相加
        List<OrderCustomerQuantityDTO> orderTraceQuantityList = getQuantityList(orderTraceTableName, goodsSql,OrderCustomerQuantityDTO.class);



        //查询t_order_goods_returns数据  退货商品表
        String returnsSql="select order_customer_goods_id as id, quantity,0.0 as \"returnReceivedQuantity\" ,order_goods_returns_status as status from " +
                orderGoodsReturnsTableName+
                " where  order_customer_goods_id IN " + whereSql +"and deleted=0";

        List<OrderCustomerQuantityDTO> refundQuantityList=getQuantityList(orderGoodsReturnsTableName, returnsSql,OrderCustomerQuantityDTO.class);



        //获取订单商品收货信息
        String acceptSql="select a.order_customer_goods_id as id, a.quantity,  0.0 AS \"returnReceivedQuantity\",-1 status  from " +
                orderGoodsAcceptTableName+ " a "+
                " where  order_customer_goods_id IN " + whereSql +"and a.deleted=0 ";

        List<OrderCustomerQuantityDTO> acceptQuantityList=getQuantityList(orderGoodsAcceptTableName, acceptSql,OrderCustomerQuantityDTO.class);

        for (Map<String, Object> map : maps) {



            MuYuanOrderGoodsDTO dto = JSONObject.parseObject(JSONObject.toJSONString(map), MuYuanOrderGoodsDTO.class);


            //转换
            OrderCustomerQuantityDTO orderCustomerQuantityDTO = JSONObject.parseObject(JSONObject.toJSONString(dto), OrderCustomerQuantityDTO.class);

            List<OrderCustomerQuantityDTO> goodsQuantityList = Arrays.asList(orderCustomerQuantityDTO);
            double goodsQuantity = sum(goodsQuantityList, quantityFun);


            double receivedQuantity = sum(acceptQuantityList.stream().filter(t -> t.getId().equals(dto.getId())).collect(Collectors.toList()), quantityFun);


            double refundQuantity = sum(refundQuantityList.stream().filter(t -> t.getId().equals(dto.getId())).collect(Collectors.toList()), quantityFun);


            double goodsReturnReceivedQuantity = sum(goodsQuantityList, returnQuantityFun);

            List<OrderCustomerQuantityDTO> tempRefundQuantityList = refundQuantityList.stream().filter(t->t.getId().equals(String.valueOf(map.get("id")))).filter(t -> !OrderGoodsReturnsStatusEnum.Done.name().equals(t.getStatus())).collect(Collectors.toList());


            if (receivedQuantity > 0 && !CollectionUtils.isEmpty(tempRefundQuantityList)) {
                double tempRefundQuantity = sum(refundQuantityList.stream().filter(t -> t.getId().equals(dto.getId())).collect(Collectors.toList()), quantityFun);
                if (tempRefundQuantity > MYBigDecimalUtils.sub(receivedQuantity, goodsReturnReceivedQuantity)) {
                    goodsReturnReceivedQuantity = receivedQuantity;
                } else {
                    goodsReturnReceivedQuantity = MYBigDecimalUtils.add(tempRefundQuantity, goodsReturnReceivedQuantity);
                }
            }

            //总退数量-退已收货数量，为什么这么做：退已收的和已收货数量相重叠
            refundQuantity = MYBigDecimalUtils.sub(refundQuantity, goodsReturnReceivedQuantity);

            double undeliveredQuantity = MYBigDecimalUtils.sub(MYBigDecimalUtils.sub(goodsQuantity, receivedQuantity), refundQuantity);

            double tranQuantity = sum(orderTraceQuantityList.stream().filter(t -> t.getId().equals(dto.getId())).collect(Collectors.toList()), quantityFun);

            BigDecimal returnedQuantity = Optional.ofNullable(dto.getReturnedQuantity()).orElse(BigDecimal.valueOf(0.0));
            BigDecimal returnReceivedQuantity = Optional.ofNullable(dto.getReturnReceivedQuantity()).orElse(BigDecimal.valueOf(0.0));

            double receivableQuantity = MYBigDecimalUtils.add(MYBigDecimalUtils.sub(MYBigDecimalUtils.sub(tranQuantity, receivedQuantity), returnedQuantity.doubleValue()),returnReceivedQuantity.doubleValue());

            map.put("receivableQuantity",receivableQuantity);
            map.put("extends_attr",undeliveredQuantity);
        }


    }




    private  <T> List<T> getQuantityList(String tableName, String sql,Object obj) {

        log.info("===============开始查询==============");
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql,new HashMap<>(7));


        log.info("=====牧原专区-订单-计算未交付数量{}表数据,查询条件为:{},查询结果为{}", tableName, sql,JSONObject.toJSONString(list));


        log.info("============结束查询=================");
        //map转换成实体类
        List<Object> collect = list.stream().map(x -> JSONObject.parseObject(JSONObject.toJSONString(x), (Type) obj)).collect(Collectors.toList());
        return (List<T>) collect;
    }



    public static <T> double sum(List<T> params, BiFunction<T, Double, Double> function) {

        double result = 0.0;

        if (org.springframework.util.CollectionUtils.isEmpty(params)) {
            return result;
        }
        for (T param : params) {
            result = function.apply(param, result);
        }

        return result;
    }













    /**
     * 获取应用表名(可获取其他应用表名)
     *
     * @param appCode
     * @param schemaCode
     * @return
     */
    public String getTableName(String appCode, String schemaCode) {
        if (StringUtils.isBlank(appCode)) {
            return getTableName(schemaCode);
        }
        return String.format("%s.i_%s_%s", appCode.toLowerCase(), appCode.toLowerCase(), schemaCode.toLowerCase());
    }

    /**
     * 获取表名称
     *
     * @param schemaCode
     * @return
     */
    public String getTableName(String schemaCode) {
        return tableHelper.getTableName(schemaCode);
    }






}


